/*******************************************************************************
 * Copyright (c) 2011 LegSem.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl-3.0.txt
 * 
 * Contributors:
 *     LegSem - initial API and implementation
 ******************************************************************************/
package com.legstar.eci.xmi;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.legstar.xsd.InvalidParameterException;
import com.legstar.xsd.XsdMappingException;

/**
 * ECI XMI to COBOL-annotated XML schema using file system.
 * <p/>
 * An extension of the core API that deals with reading/ writing to the file
 * system.
 * 
 */
public class EciXmiToXsdIO extends EciXmiToXsd {

    /** Execution parameters set. */
    private EciXmiToXsdModel _model;

    /** Logger. */
    private final Log _log = LogFactory.getLog(getClass());

    /**
     * Construct from an execution parameter set.
     * 
     * @param model the execution parameters
     */
    public EciXmiToXsdIO(final EciXmiToXsdModel model) {
        _model = model;
    }

    /**
     * Generates a COBOL annotated schema for a single or multiple ECI wsdl
     * files.
     * 
     * @throws IOException if basic read/write operation fails
     * @throws XsdMappingException if translation fails
     * @throws InvalidParameterException if one of the parameters is invalid
     */
    public void execute() throws InvalidParameterException, IOException,
            XsdMappingException {

        _log.info("ECI to COBOL-annotated XML schema translator started");
        _log.info("Execution parameters : " + getModel().toString());

        checkParameters();

        File inputEciWsdlFile = getModel().getInputEciWsdlFile();
        String inputEciWsdlFileEcoding = getModel()
                .getInputEciWsdlFileEncoding();
        File target = getModel().getTargetXsdFile();

        if (inputEciWsdlFile.isFile()) {
            if (FilenameUtils.getExtension(target.getPath()).length() == 0) {
                FileUtils.forceMkdir(target);
            }
            execute(inputEciWsdlFile, inputEciWsdlFileEcoding, target);
        } else {
            FileUtils.forceMkdir(target);
            FilenameFilter filter = new WildcardFileFilter(getModel()
                    .getInputEciWsdlFileFilter());
            for (File eciWsdlFile : inputEciWsdlFile.listFiles(filter)) {
                if (eciWsdlFile.isFile()) {
                    execute(eciWsdlFile, inputEciWsdlFileEcoding, target);
                }
            }
        }

        _log.info("ECI to COBOL-annotated XML schema translator ended");
    }

    /**
     * Execute the translation from ECI WSDL to LegStar XML Schema.
     * 
     * @param eciWsdlFile the file containing ECI XMI wsdl
     * @param eciWsdlFileEncoding the character set used to encode the ECI XMI
     *            wsdl source file
     * @param target can either be a folder where XML schema result is to be
     *            written or a file in which case the XML schema is written
     *            there
     * @return the XML Schema
     * @throws IOException if writing XSD file fails
     * @throws XsdMappingException if translation fails
     */
    public File execute(final File eciWsdlFile,
            final String eciWsdlFileEncoding, final File target)
            throws IOException, XsdMappingException {

        _log.info("Translating file : " + eciWsdlFile.toString());

        String xsdString = translate(eciWsdlFile, eciWsdlFileEncoding);
        File xsdFile = null;
        if (target.isDirectory()) {
            String xsdFileName = FilenameUtils.getBaseName(eciWsdlFile
                    .getPath()) + ".xsd";
            xsdFile = new File(target, xsdFileName);
        } else {
            xsdFile = target;
        }
        FileUtils.writeStringToFile(xsdFile, xsdString, OUTPUT_XSD_ENCODING);
        return xsdFile;
    }

    /**
     * Sanity checks this model.
     * 
     * @throws InvalidParameterException if a parameter is invalid
     */
    public void checkParameters() throws InvalidParameterException {

        if (getModel().getInputEciWsdlFile() == null) {
            throw new InvalidParameterException(
                    "No input ECI WSDL file or folder was specified");
        }
        if (getModel().getInputEciWsdlFile().exists()) {
            if (getModel().getInputEciWsdlFile().isDirectory()
                    && getModel().getInputEciWsdlFile().list().length == 0) {
                throw new IllegalArgumentException("Folder '"
                        + getModel().getInputEciWsdlFile() + "' is empty");
            }
        } else {
            throw new IllegalArgumentException("Input file or folder '"
                    + getModel().getInputEciWsdlFile() + "' not found");
        }

        if (getModel().getTargetXsdFile() == null) {
            throw new InvalidParameterException(
                    "No target folder or file was specified for COBOL-annotated XML schema");
        }

    }

    /**
     * @return the execution parameters set
     */
    public EciXmiToXsdModel getModel() {
        return _model;
    }

}
